package org;

import org.entities.Block;
import org.entities.LevelObject;
import org.entities.Player;
import org.entities.Shoot;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.FadeOutTransition;



public class GameState extends BasicGameState {

    public static float mapX = 0;
    public static float mapY = 0;
    public static BlockMap bmap;
    public static String mapName;
    public Image dashboard;
    private StateBasedGame game;
    public Input input;
    public static boolean restartGame;
    public static boolean up,  down,  left,  right,  jump,  action1,  shoot,boost,jumpRelease;
    //private Image hud1;
    //public boolean showDashboard;
    public static boolean transition;   
    public static int viewWidth = 400;
    public static int viewHeight = 300;
    public static final int ID = 2;
    private int remainingDelta = 0;
    
    public int getID() {
        return ID;
    }

    public void init(GameContainer container, StateBasedGame game) throws SlickException {
        container.setVSync(true);
        //container.setSmoothDeltas(true);
        //container.setMinimumLogicUpdateInterval(1);
        //container.setMaximumLogicUpdateInterval(1);
        this.game = game;
        Progress.initial=true;  // ship appear only at new game..once
        bmap = new BlockMap("data/level/level0001.tmx");
        if (!LevelObject.debugMode)
            container.setShowFPS(false);
        // =================
        // set player status
        // =================
        Progress.shields =30;
        Progress.health =100;
        Progress.energy =100;
        Progress.strength =100;

    }

    public static void adjustCam() {

        mapX = 180- BlockMap.Samus.x;
        mapY = 150 - BlockMap.Samus.y;

        if (mapX > 0) {
            mapX = 0;
        }
        if (mapY > 0) {
            mapY = 0;
        }
        if (mapX < -(BlockMap.mapWidth - viewWidth)) {
            mapX = -(BlockMap.mapWidth - viewWidth);
        }
        if (mapY < -(BlockMap.mapHeight - viewHeight)) {
            mapY = -(BlockMap.mapHeight - viewHeight);
        }
    }

    public static void senseKey(GameContainer container) {

        if (container.getInput().isKeyDown(Input.KEY_LEFT)) {left = true;} else {left = false;}
        if (container.getInput().isKeyDown(Input.KEY_RIGHT)) {right = true;} else {right = false;}
        if (container.getInput().isKeyDown(Input.KEY_UP)) {up = true;} else {up = false;}
        if (container.getInput().isKeyDown(Input.KEY_DOWN)) {down = true;} else {down = false;}
        if (container.getInput().isKeyDown(Input.KEY_X)) {jump = true; jumpRelease=false;} else {jump = false;}
        if (container.getInput().isKeyDown(Input.KEY_C)) {shoot = true;} else {shoot = false;}
        if (container.getInput().isKeyDown(Input.KEY_RETURN)) {action1 = true;} else {action1 = false;}
        if (container.getInput().isKeyDown(Input.KEY_V)) {boost = true;} else {boost = false;}
    }

    public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {

        if (!Progress.musicCtrl){
            Progress.musicCtrl=true;            
            BlockMap.music.loop(1,Progress.musicVol/20);
        }
        senseKey(container);

        if (!(restartGame)) {
            
            delta += remainingDelta;
            remainingDelta = delta % 5;
            for (int i=0;i<delta/5;i++) {
                BlockMap.Samus.update(10); 
            }

            adjustCam();

            // update all entities beside blocks and player
            for (int i = 0; i < BlockMap.entities.size(); i++) {
                LevelObject entity = (LevelObject) BlockMap.entities.get(i);
                if (!(entity instanceof Player)&&!(entity instanceof Block)&&!(entity instanceof Shoot))
                    entity.update(delta);
                if (entity instanceof Shoot)
                    entity.update(20);
            }
            if (Progress.health <= 0) {                
                game.enterState(GameOver.ID, new FadeOutTransition(Color.black),new FadeInTransition(Color.black));
                Progress.gameOver=true;
                System.out.printf("player shields =[%d]\n",BlockMap.Samus.getShields());
            }

            if (transition) {
                bmap = null;                
                restartGame = true;
                transition = false;
                game.enterState(Transition.ID, null, null);
                System.out.printf("level transition\n");
            }
        } 
    }

    public static boolean entityCollisionWith(LevelObject entity) throws SlickException {

        for (int i = 0; i < BlockMap.entities.size(); i++) {
            LevelObject entity1 = (LevelObject) BlockMap.entities.get(i);            
            if (entity != entity1) {
                   // &&
                   // !(entity1.x>entity.x+80)&&!(entity1.x<entity.x-32)&&
                   // !(entity1.y>entity.y+80)&&!(entity1.y<entity.y-32)) {

                if (entity.isCollisionWith(entity1)) {
                    return true;//entity.collidedWith(entity1);
                }       
            }
        }        
        return false;
    }

    public void render(GameContainer container, StateBasedGame game, Graphics g) {

        if (!(restartGame)) {
            if (!LevelObject.debugMode)
                g.scale(2f, 2f);

            // ===============
            // render scenery
            // ===============
            BlockMap.tmap.render(
                    (int) mapX % 16,
                    (int) mapY % 16,
                    (int) (-mapX / 16),
                    (int) (-mapY / 16),
                    (viewWidth / 16) + 2,
                    (viewHeight / 16) + 2,
                    1, false);

            // =============================
            // render map background objects
            // =============================
            BlockMap.tmap.render(
                    (int) mapX % 16,
                    (int) mapY % 16,
                    (int) (-mapX / 16),
                    (int) (-mapY / 16),
                    (viewWidth / 16) + 2,
                    (viewHeight / 16) + 2,
                    2, false);

            if (!LevelObject.debugMode){
                g.translate(mapX, mapY);
                for (int i = 0; i < BlockMap.entities.size(); i++) {
                    LevelObject entity = (LevelObject) BlockMap.entities.get(i);                
                    entity.draw(g);
                }
                g.resetTransform();
            }
            if (!LevelObject.debugMode)
                g.scale(2f, 2f);

            // =============================
            // render map foreground objects
            // =============================

            BlockMap.tmap.render(
                    (int) mapX % 16,
                    (int) mapY % 16,
                    (int) (-mapX / 16),
                    (int) (-mapY / 16),
                    (viewWidth / 16) + 2,
                    (viewHeight / 16) + 2,
                    3, false);          
            
            if (LevelObject.debugMode){
                g.translate(mapX, mapY);
                for (int i = 0; i < BlockMap.entities.size(); i++) {
                    LevelObject entity = (LevelObject) BlockMap.entities.get(i);                
                    entity.draw(g);
                }
                g.resetTransform();
            }

        }
    }

    @Override
    public void keyReleased(int key, char c) {

        if (key==Input.KEY_X){
            jumpRelease=true;
        }
        if (key==Input.KEY_F11){
            game.enterState(GameOver.ID, new FadeOutTransition(Color.black),new FadeInTransition(Color.black));
            Progress.gameOver=true;
        }
        if (key == Input.KEY_ESCAPE) {
            BlockMap. music.stop(); //.pause();
            Progress.musicCtrl=false;
            game.enterState (TitleState.ID,new FadeOutTransition(Color.black),new FadeInTransition(Color.black));
        }
        if (key == Input.KEY_LSHIFT) {
            MapState.loopCtrl=false;
            MapState.clrClip =false;
            game.enterState (MapState.ID,new FadeOutTransition(Color.black),new FadeInTransition(Color.black));
        }
        if (key == Input.KEY_TAB) {
            game.enterState (StatusState.ID,new FadeOutTransition(Color.black),new FadeInTransition(Color.black));
        }     
    }
}
